// use std::ops::Deref;
// use crate::List::{Cons, Nil};
use std::cell::RefCell;
use std::rc::{Rc, Weak};

// struct MyBox<T> (T);

// impl<T> MyBox<T>  {
//     fn new(x: T) -> MyBox<T> {
//         MyBox(x)
//     }
// }

// impl<T> Deref for MyBox<T> {
//     type Target = T;

//     fn deref(&self) -> &T {
//         &self.0
//     }

// }

// fn sayHello(name: &str) {
//     print!("hello, {}",name);
// }


fn main() {
    // let x = 5;
    // let y = MyBox::new(x);
    // Box可以当作引用来使用
    // let z = Box::new(x);

    // assert_eq!(5, x);
    // 解引用
    // assert_eq!(5, *y);
    // assert_eq!(5, *z);

    // let m = MyBox::new(String::from("Rust"));
    // 自动解引用（隐式借引用 ）
    // sayHello(&m);

    // let c: CustomSmartPointer = CustomSmartPointer{data: String::from("my stuff")};
    // drop(c);
    // let d = CustomSmartPointer{data: String::from("other stuff")};
    // println!("CustomSmartPointer created!");

    // let list = Cons(1, Cons(2, Nil));
    // let list = Cons(1, 
        // Box::new(Cons(2, 
            // Box::new(Cons(3, 
                // Box::new(Nil))))));

    // let b = Cons(4, Box::new(list));
    // list 已经失去所有权
    // let c = Cons(5, Box::new(list));
    // 这里我们就可以用到Rc的这个trait
    // let d = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
    // println!("{}",Rc::strong_count(&d));

    // {
        // let b = Cons(3, Rc::clone(&d));
        // println!("{}",Rc::strong_count(&d));
        // d的智能指针会增加到2，每次使用增加1，离开作用域则减少一次引用，如果引用为零，则自动消除，无法再次使用。
    // }
    
    // let c = Cons(4, Rc::clone(&d));
    // println!("{}",Rc::strong_count(&d));

    // let value = Rc::new(RefCell::new(5));
    // let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil)));
    // let b = Cons(Rc::new(RefCell::new(6)), Rc::clone(&a));
    // let c = Cons(Rc::new(RefCell::new(10)), Rc::clone(&a));

    // *value.borrow_mut() += 10;

    // println!("{:?}", a);
    // println!("{:?}", b);
    // println!("{:?}", c);

    // let a = Rc::new(Cons(5, RefCell::new(Rc::new(Nil))));

    // println!("a initial rc count = {}", Rc::strong_count(&a));
    // println!("a next item = {:?}", a.tail());

    // let b = Rc::new(Cons(10, RefCell::new(Rc::clone(&a))));
    // println!("a rc count after b creation = {}", Rc::strong_count(&b));
    // println!("b initial rc count = {}", Rc::strong_count(&b));
    // println!("b next item = {:?}", b.tail());

    // if let Some(link) = a.tail() {
    //     *link.borrow_mut() = Rc::clone(&b);
    // }

    // println!("a rc count after change a = {}", Rc::strong_count(&a));
    // println!("b rc count after change a = {}", Rc::strong_count(&b));

    // // 内存溢出
    // println!("a next item = {:?}", a.tail());

    let leaf = Rc::new(Node {
        value: 3,
        parent: RefCell::new(Weak::new()),
        children: RefCell::new(vec![]),
    });

    // println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());

    println!(
        "leaf strong = {}, weak = {}",
        Rc::strong_count(&leaf),
        Rc::weak_count(&leaf),
    );

    {
        let branch = Rc::new(Node {
            value: 5,
            parent: RefCell::new(Weak::new()),
            children: RefCell::new(vec![Rc::clone(&leaf)]),
        });
        *leaf.parent.borrow_mut() = Rc::downgrade(&branch); 
        println!(
            "branch strong = {}, weak = {}",
            Rc::strong_count(&branch),
            Rc::weak_count(&branch),
        );
        println!(
            "leaf strong = {}, weak = {}",
            Rc::strong_count(&leaf),
            Rc::weak_count(&leaf),
        );
    }

    println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());
    println!(
        "leaf strong = {}, weak = {}",
        Rc::strong_count(&leaf),
        Rc::weak_count(&leaf),
    );

}

// impl List {
//     fn tail(&self) -> Option<&RefCell<Rc<List>>> {
//         match self {
//             Cons(_, item) => Some(item),
//             Nil => None,
//         }
//     }
// }

// struct CustomSmartPointer {
//     data: String,
// }

// impl Drop for CustomSmartPointer {
//     fn drop(&mut self) {
//         println!("{}",self.data)
//     }
// }

// #[derive(Debug)]
// enum List {
//     Cons(i32, RefCell<Rc<List>>),
//     Nil,
// }

// enum List {
//     Cons(Rc<RefCell<i32>>, Rc<List>),
//     Nil,
// }

// enum List {
//     Cons(i32, Rc<List>),
//     Nil,
// }

// enum CellList {
//     Cons(Rc<RefCell<i32>>,Rc<List>),
//     Nil,
// }


#[derive(Debug)]
struct Node {
    value: i32,
    parent: RefCell<Weak<Node>>,
    children: RefCell<Vec<Rc<Node>>>,
}






